package com.sevennotes.classtable.ui.pages.components

import android.graphics.Paint
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.*
import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.Fill
import androidx.compose.ui.graphics.nativeCanvas
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.sevennotes.classtable.model.ClassRecordMonthStatis
import com.sevennotes.classtable.utils.FakeDataUtil

@Composable
fun BarChart(
  data: List<ClassRecordMonthStatis>,
  chartHeight: Dp = 300.dp,
  maxValue: Int? = null
) {
  val innerMaxValue = maxValue ?: data.maxOfOrNull { it.total } ?: 0
  val barSpacing = 16.dp
  val barWidth = 16.dp
  val color = MaterialTheme.colors.primary

  Column(
    modifier = Modifier
      .fillMaxWidth()
      .padding(start = 16.dp, top = 16.dp, end = 16.dp, bottom = 32.dp)
  ) {
    Canvas(
      modifier = Modifier
        .fillMaxWidth()
        .height(chartHeight)
    ) {
      drawBars(data, innerMaxValue, barSpacing, barWidth, color)
    }
  }
}

private fun DrawScope.drawBars(
  data: List<ClassRecordMonthStatis>,
  maxValue: Int,
  barSpacing: Dp,
  barWidth: Dp,
  color: Color
) {
  val barCount = data.size
  val totalSpacing = (barCount - 1) * barSpacing.toPx()
  val totalBarWidth = barCount * barWidth.toPx()
  val startXOffset = (size.width - totalSpacing - totalBarWidth) / 2

  var currentX = startXOffset
  val paint = Paint().apply {
    strokeWidth = 2f
    textSize = 30f
  }

  drawContext.canvas.nativeCanvas.drawLine(
    0f - barSpacing.toPx(),
    size.height,
    size.width + barSpacing.toPx(),
    size.height,
    paint
  )

  data.forEach { item ->
    val value = item.total
    val month = item.month
    val barHeight = (value.toFloat() / maxValue) * size.height

    drawRect(
      color = color,
      topLeft = Offset(currentX, size.height - barHeight),
      size = androidx.compose.ui.geometry.Size(barWidth.toPx(), barHeight),
      style = Fill
    )

    var textWidth = paint.measureText(value.toString())
    drawContext.canvas.nativeCanvas.drawText(
      value.toString(),
      currentX + (barWidth.toPx() - textWidth) / 2,
      size.height - barHeight - 4.dp.toPx(),
      paint
    )

    val monthText = "${month}月"
    textWidth = paint.measureText(monthText)
    drawContext.canvas.nativeCanvas.drawText(
      monthText,
      currentX + (barWidth.toPx() - textWidth) / 2,
      size.height + 12.dp.toPx(),
      paint
    )

    currentX += barWidth.toPx() + barSpacing.toPx()
  }
}

@Preview(showBackground = true)
@Composable
fun BarChartPreview() {
  BarChart(data = FakeDataUtil.getClassRecordStatisData())
}